﻿using Hx.ADSyncPlatform.Db;
using Hx.ADSyncPlatform.Entity.Entities;
using Hx.ADSyncPlatform.User;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Logging;
using NLog;
using System;
using System.IO;
using System.Net;

namespace Hx.ADSyncPlatform.Common.Log
{
    public class LogHelper
    {

        private DbSet<Plat_OperateLog> logDbSet;
        private IHttpContextAccessor _httpContextAccessor;
        private IUser user;
        readonly Logger logger;
        private LogHelper(Logger logger)
        {
            this.logger = logger;
        }
        /// <summary>
        /// 默认 ${logger} (Default 文件夹下)
        /// </summary>
        public static LogHelper Default { get; private set; }
        static LogHelper()
        {
            Default = new LogHelper(NLog.Web.NLogBuilder.ConfigureNLog("nlog.config").GetLogger("Default"));
        }

        public void Debug(string msg, params object[] args)
        {
            logger.Debug(msg, args);
        }
        public void Debug(string msg, Exception err)
        {
            logger.Debug(err, msg);
        }

        public void Info(string msg, params object[] args)
        {
            logger.Info(msg, args);
        }

        public void Info(string msg, Exception err)
        {
            logger.Info(err, msg);
        }

        public void Trace(string msg, params object[] args)
        {
            logger.Trace(msg, args);
        }

        public void Trace(string msg, Exception err)
        {
            logger.Trace(err, msg);
        }

        public void Error(string msg, params object[] args)
        {
            logger.Error(msg, args);
        }

        public void Error(string msg, Exception err)
        {
            logger.Error(err, msg);
        }

        public void Fatal(string msg, params object[] args)
        {
            logger.Fatal(msg, args);
        }

        public void Fatal(string msg, Exception err)
        {
            logger.Fatal(err, msg);
        }
        /// <summary>
        /// 自定义 ${logger} (我用于区分文件夹)
        /// </summary>
        /// <param name="name"></param>
        public LogHelper(string name) : this(NLog.Web.NLogBuilder.ConfigureNLog("nlog.config").GetLogger(name))
        {
        }
        public LogHelper(DbContext db, IHttpContextAccessor _httpContextAccessor, IUser user)
        {
            this.logDbSet = db.DbSet<Plat_OperateLog>();
            this.user = user;
            this._httpContextAccessor = _httpContextAccessor;
        }

        public void WriteToDb(BehaviorType behaviorType, string message, DateTime? beginTime = null, DateTime? endTime = null)
        {
            try
            {
                var log = BuildLog(behaviorType, message);
                logDbSet.InsertAsync(log);
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex);
            }

        }
        public void ExceptionToDb(string msg)
        {
            try
            {
                var log = BuildLog(BehaviorType.Exception, msg);
                logDbSet.InsertAsync(log);
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex);
            }

        }


        private Plat_OperateLog BuildLog(BehaviorType behaviorType, string message
            , DateTime? beginTime = null, DateTime? endTime = null)
        {
            var log = new Plat_OperateLog()
            {
                Id = Guid.NewGuid(),
                RequestAddress = GetRequestUrl(),
                RequestBody = GetRequestBody(),
                IP = GetClientIP(),
                ServerIP = GetServerAddressIP(),
                RequestType = GetRequestMethodType(),
                LogMessage = message,
                BehaviorType = behaviorType.ToString(),
                OperateTime = DateTime.Now

            };
            if (behaviorType == BehaviorType.Exception)
            {
                log.OperateResult = "Fail";
            }
            if (beginTime.HasValue && endTime.HasValue)
            {
                log.OperateBeginTime = beginTime;
                log.OperateEndTime = endTime;
                log.OperateTimeConsuming = (long?)(endTime.Value - beginTime.Value).TotalMilliseconds;
            }
            if (user.IsAuthenticated())
            {
                log.OperatePlatManagerId = user.ID.ToString();
                log.OperatePlatManager = user.Name;
            }
            return log;
        }

        private string GetRequestMethodType()
        {
            return _httpContextAccessor.HttpContext.Request.Method;
        }


        private string GetClientIP()
        {
            try
            {
                string ipaddress = _httpContextAccessor.HttpContext.Connection.RemoteIpAddress.ToString();
                return ipaddress;
            }
            catch (Exception)
            {

                return "";
            }

        }

        private string GetServerAddressIP()
        {
            try
            {
                ///获取本地的IP地址
                string AddressIP = string.Empty;
                foreach (IPAddress _IPAddress in Dns.GetHostEntry(Dns.GetHostName()).AddressList)
                {
                    if (_IPAddress.AddressFamily.ToString() == "InterNetwork")
                    {
                        AddressIP = _IPAddress.ToString();
                    }
                }
                return AddressIP;
            }
            catch (Exception)
            {
                return "";
            }
        }

        private string GetRequestUrl()
        {
            try
            {
                return _httpContextAccessor.HttpContext.Request.Path;
            }
            catch (Exception)
            {
                return "";
            }
        }

        private string GetRequestBody()
        {
            try
            {
                if (_httpContextAccessor.HttpContext.Request.Body.Length > 0)
                {
                    _httpContextAccessor.HttpContext.Request.Body.Position = 0;
                    var reader = new StreamReader(_httpContextAccessor.HttpContext.Request.Body);
                    var contentFromBody = reader.ReadToEnd();
                    _httpContextAccessor.HttpContext.Request.Body.Position = 0;
                    return contentFromBody;
                }
                return "";


            }
            catch (Exception)
            {
                return "";
            }
        }

    }
}
